
/* <primitive: 210>
 * <VMMirror> readByteFromPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primReadByteFromPort()
{
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned char answer;
		
		__asm__ __volatile__("in %1 , %0" : "=a" (answer) : "d" (portNumber));
		
		popNandPush(2, packSmInt( (int)answer ));	
	}
}

/* <primitive: 211>
 * <VMMirror> writeByte: value <Integer> toPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primWriteByteToPort()
{
	int v = unpackSmInt(peek(1));
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767 || v<0 || v>255) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned char value = (unsigned char)v;
	
		__asm__ __volatile__("out %0, %1" :: "a" (value), "d" (portNumber));
		
		popNandPush(3, packSmInt( (int)value ));
	}
}

/* <primitive: 212>
 * <VMMirror> readShortFromPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primReadShortFromPort()
{
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned short answer;
		
		__asm__ __volatile__("in %1 , %0" : "=a" (answer) : "d" (portNumber));
		
		popNandPush(2, packSmInt( (int)answer ));	
	}
}

/* <primitive: 213>
 * <VMMirror> writeShort: value <Integer> toPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primWriteShortToPort()
{
	int v = unpackSmInt(peek(1));
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767 || v<0 || v>32767) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned short value = (unsigned short)v;
	
		__asm__ __volatile__("out %0, %1" :: "a" (value), "d" (portNumber));
		
		popNandPush(3, packSmInt( (int)value ));
	}
}
		
/* <primitive: 214>
 * <VMMirror> readLongFromPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primReadLongFromPort()
{
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned char answer;
		
		__asm__ __volatile__("in %1 , %0" : "=a" (answer) : "d" (portNumber));
		
		popNandPush(2, packPos32( (int)answer ));	
	}
}

/* <primitive: 215>
 * <VMMirror> writeLong: value <Integer> toPort: portNumber <Integer> ^<Integer>
 * .
 * Essential.
 */
void primWriteLongToPort()
{
	unsigned int v = unpackPos32(peek(1));
	int n = unpackSmInt(peek(0));
	if(n<0 || n>32767) success=0;
	if(success)
	{
		unsigned short portNumber = (unsigned short)n;
		unsigned int value = (unsigned int)v;
	
		__asm__ __volatile__("out %0, %1" :: "a" (value), "d" (portNumber));
		
		popNandPush(3, peek(1));
	}
}

/* <primitive: 216>
 * <VMMirror> read: buffer <ByteOrWordIndexable> from: address <Integer> ^<ByteOrWordIndexable>
 *
 * Direct access to memory.  Reads enough bytes to fill the buffer.
 * Essential.
 */
void primReadFromAddress()
{
	int buffer = peek(1);
	unsigned int address = unpackPos32(peek(0));

	int fmt = formatOf(buffer);
	int length;
	
	if(fmt==6) //word indexable
		length = sizeOf(buffer)*4;  
	else if(fmt>=8 && fmt<=11) //byte indexable
		length = sizeOf(buffer)*4 - (fmt&3);
	else
		success=0;
	
	if(success)
	{		
		unsigned char* src = (unsigned char*)address;
		unsigned char* dst = (unsigned char*)(buffer+4);
		
		memcpy(dst, src, length);
		
		popNandPush(3, buffer);
	}
}

/* <primitive: 217>
 * <VMMirror> write: buffer <ByteOrWordIndexable> to: address <Integer> ^<ByteOrWordIndexable>
 *
 * Direct access to memory.  Writes all bytes in buffer.
 * Essential.
 */
void primWriteToAddress()
{
	int buffer = peek(1);
	unsigned int address = unpackPos32(peek(0));

	int fmt = formatOf(buffer);
	int length;
	
	if(fmt==6) //word indexable
		length = sizeOf(buffer)*4;  
	else if(fmt>=8 && fmt<=11) //byte indexable
		length = sizeOf(buffer)*4 - (fmt&3);
	else
		success=0;
	
	if(success)
	{		
		unsigned char* dst = (unsigned char*)address;
		unsigned char* src = (unsigned char*)(buffer+4);
		
		memcpy(dst, src, length);
		
		popNandPush(3, buffer);
	}
}

/* <primitive: 218>
 * <VMMirror> 
 * read: length <Integer> 
 * from: address <Integer>
 * into: buffer <ByteOrWordIndexable>
 * startingAt: offset <Integer> ^<ByteOrWordIndexable>
 * 
 * Direct access to memory.  Offset is 0-origin, units are bytes.
 * Essential.
 */
void primReadFromAddressBounded()
{	
	int length = unpackSmInt(peek(3)); 
	unsigned int address = unpackPos32(peek(2));
	int buffer = peek(1);
	int offset = unpackSmInt(peek(0));
	
	int fmt = formatOf(buffer);
	//BOGUS: ALSO CHECK BOUNDS
	
	if(fmt==6) //word indexable
	{}
	else if(fmt>=8 && fmt<=11) //byte indexable
	{}
	else
		success=0;

	if(success)
	{
		//check format is byte or word indexable
		//check range is inside buffer
		
		unsigned char* src = (unsigned char*)address;
		unsigned char* dst = (unsigned char*)(buffer+4+offset);
		
		memcpy(dst, src, length);
		
		popNandPush(5, buffer);
	}
}

/* <primitive: 219>
 * <VMMirror> 
 * write: length <Integer> 
 * to: address <Integer>
 * from: buffer <ByteOrWordIndexable>
 * startingAt: offset <Integer> ^<ByteOrWordIndexable>
 * 
 * Direct access to memory.  Offset is 0-origin, units are bytes.
 * Essential.
 */
void primWriteToAddressBounded()
{
	int length = unpackSmInt(peek(3)); 
	unsigned int address = unpackPos32(peek(2));
	int buffer = peek(1);
	int offset = unpackSmInt(peek(0));
	
	int fmt = formatOf(buffer);
	//BOGUS: ALSO CHECK BOUNDS
	
	if(fmt==6) //word indexable
	{}
	else if(fmt>=8 && fmt<=11) //byte indexable
	{}
	else
		success=0;

	if(success)
	{
		//check format is byte or word indexable
		//check range is inside buffer
		
		unsigned char* dst = (unsigned char*)address;
		unsigned char* src = (unsigned char*)(buffer+4+offset);
		
		memcpy(dst, src, length);
		
		popNandPush(5, buffer);
	}
}

/* <primitive: 220>
 * <VMMirror> debugPrint: message <String>
 * .
 * Essential.
 */
void primDebugPrint()
{
	int msg = top();
	printf("%s", symbolToCString(msg)); //note conversion has 1000 character limit
#ifdef PROGRAM
	fflush(stdout);
#endif	
	popNandPush(2, msg);
}

/* <primitive: 221>
 * <VMMirror> panic: message <String>
 * .
 * Essential.
 */
void primPanic()
{
	int msg = top();
	PANIC( symbolToCString(msg) );
	popNandPush(2, msg);
}

/* <primitive: 222>
 * <VMMirror> isOceania
 * .
 * Essential.
 */
void primIsOceania()
{
	popNandPush(argumentCount+1, true);
}
